#ifndef _NE_GLSL_SHADER_H_
#define _NE_GLSL_SHADER_H_

#include <system/Resource.h>
#include <graphics/GLObject.h>

namespace ne
{
    class NEAPI GLSLShader : public Resource, public GLObject
    {
        public:
            GLSLShader(ResourceManager *pManager,
                       const uint64_t id,
                       const std::string &name,
                       const std::string &fileName,
                       const bool isManual,
                       ManualResourceLoader *pLoader);

            void createInternalShader(const ShaderType type);

            void freeInternalShader();

            bool loadFromFile(const std::string &fileName);

            bool loadFromSourceCode(const std::string &sourceCode);

            bool isShader() const;

            bool isValidated() const;

            ShaderType getType() const;

            std::string getSourceCode() const;

            //TODO: Only can call this when isManual
            std::string getInfoLog() const;

            virtual ~GLSLShader();

        protected:
            virtual bool loadImplement();

            virtual bool unloadImplement();

            virtual bool downloadImplement();

            virtual size_t _calculateSize() const;

        private:
            ShaderType mType;
            std::string mSourceCode;
            bool mIsValidated;
    };

    class NEAPI GLSLShaderPtr : public SharedPtr<GLSLShader>
    {
        public:
            GLSLShaderPtr() : SharedPtr<GLSLShader>() {}
            explicit GLSLShaderPtr(GLSLShader *pShader) : SharedPtr<GLSLShader>(pShader) {}
            GLSLShaderPtr(const GLSLShaderPtr &pShader) : SharedPtr<GLSLShader>(pShader) {}

            GLSLShaderPtr(const ResourcePtr &p)
                : SharedPtr<GLSLShader>()
            {
                mpPtr = static_cast<GLSLShader*>(p.ptr());
                mpUseCount = p.getUseCountPtr();
                if (mpUseCount)
                {
                    ++(*mpUseCount);
                }
            }

            GLSLShaderPtr& operator = (const ResourcePtr &p)
            {
                if (mpPtr == static_cast<GLSLShader*>(p.ptr()))
                {
                    return *this;
                }
                GLSLShaderPtr temp(p);
                swap(temp);
                return *this;
            }
    };
}

#endif
